package com.atguigu.gmall.order.listener;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;
import java.util.Map;

/**
 * 订单微服务的监听器:目前监听mq发来的消息,实现两个小时后删除没有付款的订单
 */
@Component
@Slf4j
public class OrderInfoListener {
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    //取消订单
    @RabbitListener(queues = {MqConst.QUEUE_ORDER_CANCEL})
    public void cancelOrder(Long orderId, Message message, Channel channel){
        System.out.println(message + "接收: " + new Date());
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        String orderStatus = orderInfo.getOrderStatus();
        if (orderStatus.equals(OrderStatus.UNPAID.name())){
            //如果用户订单状态为未付款 修改订单状态为关闭
            //orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            //orderInfo.setProcessStatus(OrderStatus.CLOSED.name());
            //orderInfoMapper.updateById(orderInfo);
            orderInfoService.updateOrderStatus(orderInfo.getId(),ProcessStatus.CLOSED);
        }
        receiverMessage(String.valueOf(orderId),message,channel);
    }

    //修改订单状态,订单支付成功
    @RabbitListener(bindings = {@QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY,durable = "true",autoDelete = "false"),
            key = MqConst.ROUTING_PAYMENT_PAY
    )})
    public void updateOrderStatusById(Long orderID,Message message,Channel channel){
        try {
            System.out.println("接收到了订单的ID:"+ orderID + ",时间:" + new Date());

            //修改订单状态 修改为支付成功
            orderInfoService.updateOrderStatus(orderID, ProcessStatus.PAID);
            //由订单微服务发消息给库存微服务,    订单表,订单详情表 -> 仓库工作单表,仓库工作单详情表

            //初始化库存那边需要的数据
            Map initWareInfo = orderInfoService.initWareOrder(orderID);
            //发消息内容 json字符串
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,
                    MqConst.ROUTING_WARE_STOCK,
                    JSONObject.toJSONString(initWareInfo));
            //改订单状态为 已经通知库储
            orderInfoService.updateOrderStatus(orderID,ProcessStatus.NOTIFIED_WARE);
            //手动应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //接收库存系统扣减库存是否成功
    /**
     * orderId	订单系统的订单ID
     * status	状态： ‘DEDUCTED’  (已减库存)
     *         状态：  ‘OUT_OF_STOCK’  (库存超卖)
     *         {}
     */
    @RabbitListener(bindings = {@QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER),
            value = @Queue(value = MqConst.QUEUE_WARE_ORDER,durable = "true",autoDelete = "false"),
            key = MqConst.ROUTING_WARE_ORDER
    )})
    public void updateOrderStatus(String result, Message message, Channel channel){
        System.out.println("接收到扣减库存是否成功:"+result);

        Map map = JSONObject.parseObject(result,Map.class);
        if ("DEDUCTED".equals(map.get("status"))){
            //扣减库存成功 修改订单的状态
            //将订单状态修改为: 待发货 Object --> Integer --> Long 或  Object --> String --> Long
            orderInfoService.updateOrderStatus(Long.parseLong(String.valueOf(map.get("orderId"))),
                    ProcessStatus.WAITING_DELEVER);
        }else {
            //库存超卖
            orderInfoService.updateOrderStatus(Long.parseLong(String.valueOf(map.get("orderId"))),
                    ProcessStatus.STOCK_EXCEPTION);
            //打印日志转人工
        }
    }

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private OrderInfoService orderInfoService;
    //出错一次手动应答的方法
    public void receiverMessage(String msg, Message message, Channel channel) {
        //手动消息应答
        try {
            //System.out.println("直接接收消息：" + msg);
            //System.out.println("接收消息对象中的消息体：" + new String(message.getBody()));
            //int x = 10 /0;
            //basicAck : 手动应答
            //deliveryTag : 消息的标识符
            //multiple : 是否批量应答消息    预取值  prefetch: 4  表示每次获取4个消息  在信道中
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            //判断是否是已经发送的消息:是则重发一遍,不是则将队列中的消息删除掉
            if (message.getMessageProperties().isRedelivered()){
                //消息已经发送过了
                log.error("此消息不能再重发消费了:{}", JSONObject.toJSONString(message));
                //拒绝应答  将队列中的消息 删除掉 不要影响到后面的消息的处理
                //deliveryTag : 消息的标识符
                //requeue  : 要求将消息放回队列  消费者重新获取一次消息
                try {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }else {
                //1.2 是刚来的消息   给一次 重新发送消息的机会
                //deliveryTag : 消息的标识符
                //multiple : 是否批量应答消息    预取值  prefetch: 4  表示每次获取4个消息  在信道中
                //requeue  : 要求将消息放回队列  消费者重新获取一次消息
                log.info("是刚来的消息   给一次 重新发送消息的机会");
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}
